/*
    作者：zx
    时间：2022.11.13
    描述：任务结构体初始化和tss初始化
*/

#ifndef TASK_H
#define TASK_H

#include "cpu/cpu.h"
#include "comm/types.h"
#include "tools/list.h"
#include "fs/file.h"

#define TASK_NAME_SIZE 32
// 任务可以执行10次时钟中断，每次减1
#define TASK_TIME_SLICE_COUNT_DEFAULT 10
// 进程最大的打开文件数量
#define TASK_OPEN_FILE_MAX 128

// 任务的特权级，用于任务初始化时
#define TASK_TYPE_SYSTEM     (1 << 0)
#define TASK_TYPE_USER       (0 << 0)

typedef struct _task_t
{
    enum {                                   
        TASK_CREATED = 0,   // 创建态  
        TASK_READY,     // 就绪态
        TASK_RUNNING,   // 运行态
        TASK_SLEEP,     // 休眠态
        TASK_WAITTING,  // 阻塞态
        TASK_ZOMBIE,    // 濒死态
    }status;
    int running_status;

    // 父进程
    struct _task_t * parent;

    // 进程ID
    uint32_t pid;
    char name[TASK_NAME_SIZE];

    // 进程持有的堆地址
    uint32_t heap_start, heap_end;

    // 程序可以运行的最大时间片
    int time_ticks;
    // 当前程序还可以运行的时间片
    int slice_ticks;
    // 休眠时间片
    int sleep_ticks;
    // 该节点插入就绪队列
    list_node_t run_node;
    // 该节点插入全部任务队列
    list_node_t all_node;
    // 该节点插入等待队列
    list_node_t wait_node;
    // // 手动自写切换进程
    // uint32_t * stack;
    tss_t tss;
    int gdt_tss_selector;
    // 进程打开的文件
    file_t * file_table[TASK_OPEN_FILE_MAX];
}task_t;

int init_task(task_t * task, const char * name, uint32_t entry, uint32_t esp, int access);
void task_switch(task_t * from, task_t * to);
void simple_switch(uint32_t ** from, uint32_t * to);

typedef struct _task_manager_t
{   
    // 内核加载完成后，立马运行的任务：
    task_t first_task;
    // 当前运行的任务
    task_t * curr_task;
    // 空闲进程，所有进程都未就绪时，暂用cpu
    task_t idel_task;
    // 全部进程队列
    list_t task_list;
    // 休眠进程队列
    list_t sleep_list;
    // 就绪队列
    list_t ready_list;
    // 应用程序使用的代码段和数据段选择子
    int task_code_selector;
    int task_data_selector;
}task_manager_t;

// 空闲进程执行代码
void idel_task_entry(void);
// 任务管理器初始化
void task_manager_init(void);
// 最初任务初始化
void first_task_init(void);
// 最初任务的结构体指针
task_t * first_task_get(void);
// 获取当前任务的结构体指针
task_t * curr_task_get(void);
// 设置任务就绪
void task_set_to_ready(task_t * task);
// 从就绪队列取出任务
void task_remove_ready(task_t * task);
// 获取当前任务的结构体指针
task_t * curr_task_get(void);
// 下一个需要运行的任务
task_t * task_next_run(void);
// 进程主动放弃cpu
int sys_yield(void);
// 任务管理器更新，改变任务的状态、当前任务指向
void task_manager_update(void);
// 程序时间片计数器更新
void task_time_ticks(void);
// 让进程休眠ms毫秒
void sys_sleep(uint32_t ms);
// 设置任务休眠
void task_set_to_sleep(task_t * task, uint32_t tick);
// 任务唤醒
void task_set_to_wakeup(task_t * task);
// 获取任务的唯一ID
int sys_getpid(void);
// 生成子进程
int sys_fork(void);
// 运行进程
int sys_execve(char * name, char ** argv, char ** env);
// 进程退出
void sys_exit(int status);
// 进程资源回收
int sys_wait(int * status);
// 用exec时为新进程传递参数
typedef struct _task_args_t
{
    uint32_t return_addr;
    int argc;
    char ** argv;
}task_args_t;

// 为新打开的文件分配文件描述符
int task_alloc_fd(file_t * file);
void task_free_fd(int fd);
// 通过fd获取file
file_t * task_get_file(int fd);

#endif // !TASK_H